﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Collections;

namespace FixxVS
{
	[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
	public static class ListViewExtensions
	{
		[System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
		private struct LVCOLUMN
		{
			public Int32 mask;
			public Int32 cx;
			[System.Runtime.InteropServices.MarshalAs(System.Runtime.InteropServices.UnmanagedType.LPTStr)]
			public string pszText;
			public IntPtr hbm;
			public Int32 cchTextMax;
			public Int32 fmt;
			public Int32 iSubItem;
			public Int32 iImage;
			public Int32 iOrder;
		}

		private const Int32 HDI_FORMAT = 0x4;
		private const Int32 HDF_SORTUP = 0x400;
		private const Int32 HDF_SORTDOWN = 0x200;
		private const Int32 LVM_GETHEADER = 0x101f;
		private const Int32 HDM_GETITEM = 0x120b;
		private const Int32 HDM_SETITEM = 0x120c;

		[System.Runtime.InteropServices.DllImport("user32.dll")]
		private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

		[System.Runtime.InteropServices.DllImport("user32.dll", EntryPoint = "SendMessage")]
		private static extern IntPtr SendMessageLVCOLUMN(IntPtr hWnd, Int32 Msg, IntPtr wParam, ref LVCOLUMN lPLVCOLUMN);

		public static void ToggleSort(this ListView ListViewControl, int ColumnIndex)
		{
			if (ListViewControl.ListViewItemSorter == null)
				ListViewControl.ListViewItemSorter = new ListViewColumnSorter();

			ListViewColumnSorter sorter = (ListViewColumnSorter)ListViewControl.ListViewItemSorter;

			if (sorter.Order == SortOrder.None || sorter.SortColumn != ColumnIndex)
			{
				sorter.SortColumn = ColumnIndex;
				sorter.Order = SortOrder.Ascending;
			}
			else
			{
				sorter.Order = (sorter.Order == SortOrder.Ascending)
								? SortOrder.Descending
								: SortOrder.Ascending;
			}
			ListViewControl.SetSortIcon(ColumnIndex, sorter.Order);

			ListViewControl.Sort();
			

		}

		public static void SetSortIcon(this ListView ListViewControl, int ColumnIndex, SortOrder Order)
		{
			IntPtr ColumnHeader = SendMessage(ListViewControl.Handle, LVM_GETHEADER, IntPtr.Zero, IntPtr.Zero);

			for (int ColumnNumber = 0; ColumnNumber <= ListViewControl.Columns.Count - 1; ColumnNumber++)
			{
				IntPtr ColumnPtr = new IntPtr(ColumnNumber);
				LVCOLUMN lvColumn = new LVCOLUMN();
				lvColumn.mask = HDI_FORMAT;
				SendMessageLVCOLUMN(ColumnHeader, HDM_GETITEM, ColumnPtr, ref lvColumn);

				if (!(Order == SortOrder.None) && ColumnNumber == ColumnIndex)
				{
					switch (Order)
					{
						case SortOrder.Ascending:
							lvColumn.fmt &= ~HDF_SORTDOWN;
							lvColumn.fmt |= HDF_SORTUP;
							break;
						case SortOrder.Descending:
							lvColumn.fmt &= ~HDF_SORTUP;
							lvColumn.fmt |= HDF_SORTDOWN;
							break;
					}
				}
				else
				{
					lvColumn.fmt &= ~HDF_SORTDOWN & ~HDF_SORTUP;
				}

				SendMessageLVCOLUMN(ColumnHeader, HDM_SETITEM, ColumnPtr, ref lvColumn);
			}
		}

		public class ListViewColumnSorter : IComparer
		{
			
			private int ColumnToSort;
			
			private SortOrder OrderOfSort;
			
			private CaseInsensitiveComparer ObjectCompare;

			public ListViewColumnSorter()
			{
				ColumnToSort = 0;
				OrderOfSort = SortOrder.None;
				ObjectCompare = new CaseInsensitiveComparer();
			}
			public int Compare(object x, object y)
			{
				int compareResult;
				ListViewItem listviewX, listviewY;
				listviewX = (ListViewItem)x;
				listviewY = (ListViewItem)y;
				compareResult = ObjectCompare.Compare(listviewX.SubItems[ColumnToSort].Text, listviewY.SubItems[ColumnToSort].Text);
				if (OrderOfSort == SortOrder.Ascending)
				{
					return compareResult;
				}
				else if (OrderOfSort == SortOrder.Descending)
				{
					return (-compareResult);
				}
				else
				{
					return 0;
				}
			}
			public int SortColumn
			{
				set
				{
					ColumnToSort = value;
				}
				get
				{
					return ColumnToSort;
				}
			}
			public SortOrder Order
			{
				set
				{
					OrderOfSort = value;
				}
				get
				{
					return OrderOfSort;
				}
			}

		}
	
	}
}
